import 'dart:ui';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:path/path.dart';

import '../entity/artwork_model.dart';
import '../utils/common_utils.dart';

/// 自定义绘制器，用于绘制像素网格
class GridPainter extends CustomPainter {
  final ArtworkModel artworkModel;
  final double cellSize;
  late final DrawPointFunction drawPointFunction;

  GridPainter({required this.artworkModel, required this.cellSize}) {
    PointStyleModel pointStyleModel =
        artworkModel.canvas.canvasConfig.pointStyle;
    defaultDrawPointFunction(
      Canvas canvas,
      double x,
      double y,
      double size,
      Paint paint,
    ) {
      paint.style = PaintingStyle.fill;
      canvas.drawRect(
        Rect.fromCenter(center: Offset(x, y), width: size, height: size),
        paint,
      );
    }

    if (pointStyleModel.type == 'default') {
      switch (pointStyleModel.data) {
        case '1':
          drawPointFunction = defaultDrawPointFunction;
          break;
        case '2':
          drawPointFunction =
              (Canvas canvas, double x, double y, double size, Paint paint) {
                paint.style = PaintingStyle.fill;
                canvas.drawCircle(Offset(x, y), size / 2, paint);
              };
          break;
        case '3':
          drawPointFunction =
              (Canvas canvas, double x, double y, double size, Paint paint) {
                paint.style = PaintingStyle.stroke;
                paint.strokeWidth = size / 4;
                canvas.drawCircle(
                  Offset(x, y),
                  (size - paint.strokeWidth) / 2,
                  paint,
                );
              };
          break;
        case '4':
          drawPointFunction =
              (Canvas canvas, double x, double y, double size, Paint paint) {
                paint.strokeWidth = size / 4;
                var half = size * 2 / 5;
                canvas.drawLine(
                  Offset(x - half, y - half),
                  Offset(x + half, y + half),
                  paint,
                );
                canvas.drawLine(
                  Offset(x - half, y + half),
                  Offset(x + half, y - half),
                  paint,
                );
              };
          break;
        default:
          drawPointFunction =
              (Canvas canvas, double x, double y, double size, Paint paint) {
                canvas.drawRect(
                  Rect.fromCenter(
                    center: Offset(x, y),
                    width: size,
                    height: size,
                  ),
                  paint,
                );
              };
      }
    } else {
      try {
        // 预先解码图片并缓存
        drawPointFunction =
            (Canvas canvas, double x, double y, double size, Paint paint) {
              final image = artworkModel
                  .canvas
                  .canvasConfig
                  .pointStyle
                  .imageCacheMap[paint.color.toHexString()];
              if (image == null) {
                paint.style = PaintingStyle.fill;
                canvas.drawRect(
                  Rect.fromCenter(
                    center: Offset(x, y),
                    width: size,
                    height: size,
                  ),
                  paint,
                );
                return;
              } else {
                // 使用已解码的图片
                canvas.drawImageRect(
                  image, // 原始图片
                  Rect.fromLTWH(
                    0,
                    0,
                    image.width.toDouble(),
                    image.height.toDouble(),
                  ),
                  Rect.fromCenter(
                    center: Offset(x, y),
                    width: size,
                    height: size,
                  ),
                  paint,
                );
              }
            };
      } catch (e) {
        CommonUtils.showToast('自定义像素点样式加载失败,更换为默认样式', context);
        drawPointFunction = defaultDrawPointFunction;
      }
    }
  }

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint();
    var fontSize = cellSize / 4,
        strokeWidth = 0.4,
        privateRectWidth = artworkModel.canvas.canvasConfig.showGrid
            ? (cellSize - strokeWidth)
            : cellSize;
    paint.strokeWidth = strokeWidth;
    ParagraphStyle style = ParagraphStyle(
      textAlign: TextAlign.center,
      fontSize: fontSize,
    );

    // 边框
    if (artworkModel.canvas.canvasConfig.showGrid) {
      paint.color = Colors.black26;
      paint.style = PaintingStyle.stroke;
      for (double i = 0; i < artworkModel.canvas.size.x; i++) {
        for (double j = 0; j < artworkModel.canvas.size.y; j++) {
          var x = CommonUtils.coverPointIdx2Point(i, cellSize),
              y = CommonUtils.coverPointIdx2Point(j, cellSize);
          canvas.drawRect(
            Rect.fromCenter(
              center: Offset(x, y),
              width: cellSize,
              height: cellSize,
            ),
            paint,
          );
        }
      }
    }

    for (var xEntry in artworkModel.canvas.pointData.entries) {
      for (var yEntry in xEntry.value.entries) {
        if (xEntry.key >= artworkModel.canvas.size.x ||
            yEntry.key >= artworkModel.canvas.size.y) {
          continue;
        }
        var x = CommonUtils.coverPointIdx2Point(xEntry.key, cellSize),
            y = CommonUtils.coverPointIdx2Point(yEntry.key, cellSize);
        paint.color = yEntry.value;
        // 绘制像素
        drawPointFunction(canvas, x, y, privateRectWidth, paint);
        if (yEntry.value == Colors.transparent) {
          continue;
        }
        // 显示坐标
        if (artworkModel.canvas.canvasConfig.showPosition) {
          final ParagraphBuilder paragraphBuilder = ParagraphBuilder(style);
          var text = '${xEntry.key.toInt() + 1}⋅${yEntry.key.toInt() + 1}';
          paragraphBuilder.pushStyle(
            ui.TextStyle(
              color: useWhiteForeground(yEntry.value)
                  ? Colors.white
                  : Colors.black,
            ),
          );
          paragraphBuilder.addText(text);
          Paragraph paragraph = paragraphBuilder.build();
          paragraph.layout(ParagraphConstraints(width: text.length * fontSize));
          canvas.drawParagraph(
            paragraph,
            Offset(
              x - paragraph.width / 2,
              y - (fontSize + paragraph.height) / 3.5,
            ),
          );
        }
      }
    }

    // 最外层边框
    paint.color = Colors.black;
    paint.style = PaintingStyle.stroke;
    paint.strokeWidth = strokeWidth;
    canvas.drawRect(
      Rect.fromPoints(Offset(0, 0), Offset(size.width, size.height)),
      paint,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

typedef DrawPointFunction =
    void Function(Canvas, double, double, double, Paint);
